package com.dbflow5.config;

import com.dbflow5.converter.TypeConverters;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description: The base interface for interacting with all of the database and top-level data that's shared
 * between them.
 */
public abstract class DatabaseHolder {

    Map<Class<?>, DBFlowDatabase> databaseDefinitionMap = new HashMap<>();
    Map<String, DBFlowDatabase> databaseNameMap = new HashMap<>();
    Map<Class<?>, DBFlowDatabase> databaseClassLookupMap = new HashMap<>();

    Map<Class<?>, TypeConverters.TypeConverter<?, ?>> typeConverters = new HashMap<>();

    public List<DBFlowDatabase> databaseDefinitions(){
        return new ArrayList<>(databaseNameMap.values());
    }

    /**
     * model
     *
     * @param clazz The model value class to get a [TypeConverter]
     * @return Type converter for the specified model value.
     */
    public TypeConverters.TypeConverter<?, ?> getTypeConverterForClass(Class<?> clazz){
        return typeConverters.get(clazz);
    }

    /**
     * getDatabaseForTable
     *
     * @param table The model class
     * @return The database that the table belongs in
     */
    public DBFlowDatabase getDatabaseForTable(Class<?> table){
        return databaseDefinitionMap.get(table);
    }

    public DBFlowDatabase getDatabase(Class<?> databaseClass){
        return databaseClassLookupMap.get(databaseClass);
    }


    /**
     * getDatabase
     *
     * @param databaseName The name of the database to retrieve
     * @return The database that has the specified name
     */
    public DBFlowDatabase getDatabase(String databaseName){
        return databaseNameMap.get(databaseName);
    }

    /**
     * Helper method used to store a database for the specified table.
     *
     * @param table              The model table
     * @param databaseDefinition The database definition
     */
    public void putDatabaseForTable(Class<?> table, DBFlowDatabase databaseDefinition) {
        databaseDefinitionMap.put(table, databaseDefinition);
        databaseNameMap.put(databaseDefinition.getDatabaseName(), databaseDefinition);
        databaseClassLookupMap.put(databaseDefinition.associatedDatabaseClassFile(), databaseDefinition);
    }

    public void reset() {
        databaseDefinitionMap.clear();
        databaseNameMap.clear();
        databaseClassLookupMap.clear();
        typeConverters.clear();
    }
}
